#pragma once

#include <iostream>
#include <queue>
#include <pthread.h>
#include "Task.hpp"

#define NUM 6

class ThreadPool
{
private:
    int num;
    bool stop;
    std::queue<Task> task_queue;
    pthread_mutex_t lock; // 锁
    pthread_cond_t cond;  // 条件变量

    // 单例模式
    static ThreadPool *_sInst;

private:
    ThreadPool(int _num = NUM) : num(_num), stop(false)
    {
        pthread_mutex_init(&lock, nullptr);
        pthread_cond_init(&cond, nullptr);
    }

    ThreadPool(const ThreadPool & s) = delete;

    ~ThreadPool()
    {
        pthread_mutex_destroy(&lock);
        pthread_cond_destroy(&cond);
    }

public:
    // 给线程池设计成为单例模式
    static ThreadPool* GetInstance()
    {
        static pthread_mutex_t _mutex = PTHREAD_MUTEX_INITIALIZER;
        if(_sInst == nullptr)
        {
            pthread_mutex_lock(&_mutex);
            if(_sInst == nullptr){
                _sInst = new ThreadPool();
                _sInst->InitThreadPool();
            }
            pthread_mutex_unlock(&_mutex);
        }
        return _sInst;
    }

    bool IsStop()
    {
        return stop;
    }
    // 判断任务队列是否为空
    bool TaskQueueIsEmpty()
    {
        // return task_queue.empty();
        return task_queue.size() == 0?true:false;
    }
    // 加锁
    void Lock()
    {
        pthread_mutex_lock(&lock);
    }
    // 解锁
    void Unlock()
    {
        pthread_mutex_unlock(&lock);
    }
    // 线程等待
    void ThreadWait()
    {
        pthread_cond_wait(&cond, &lock);
    }
    // 唤醒线程
    void ThreadWakeUp()
    {
        pthread_cond_signal(&cond);
    }
    // 线程执行的函数代码
    static void *ThreadRoutinue(void *args)
    {
        ThreadPool *tp = (ThreadPool *)(args);
        while (true)
        {
            Task t;
            tp->Lock();
            if(tp->TaskQueueIsEmpty())
            {
                tp->ThreadWait();   // 当我醒来的时候，一定是有互斥锁的
            }
            tp->PopTask(t);
            tp->Unlock();
            t.ProcessOn();
        }
    }
    // 初始化线程池
    bool InitThreadPool()
    {
        for (int i = 0; i < num; i++)
        {
            pthread_t tid;
            if (pthread_create(&tid, nullptr, ThreadRoutinue, this) != 0)
            {
                LOG(Fatal, "create thread pool error");
                return false;
            }
        }
        LOG(Info, "create thread pool success");
        return true;
    }
    // 将要做的任务放入线程池
    void PushTask(const Task &task)
    {
        Lock();
        task_queue.push(task);
        Unlock();
        ThreadWakeUp();
    }
    // 任务做完了，放出任务
    void PopTask(Task &task)
    {
        task = task_queue.front();
        task_queue.pop();
    }
};

// 单例模式
ThreadPool *ThreadPool::_sInst = nullptr;